
#include "audio_vorbis.h"
#include <io.h>

using namespace WtfAudio;
using namespace WtfEngine;

static int _fseek64_wrap(FILE *f,ogg_int64_t off,int whence){
  if(f==NULL)return(-1);
  return fseek(f,off,whence);
}

VorbisData::VorbisData(const StringPool::Entry& sFile)
: Data(sFile), mPosition(0) {
	FILE * pFile = fopen((char *)(*sFile).c_str(), "rb");
	if(pFile == NULL) {
		throw std::runtime_error(String("Failed to open vorbis file - ") + sFile);
	};
	
	ov_callbacks callbacks = {
		(size_t (*)(void *, size_t, size_t, void *))  &fread,
		(int (*)(void *, ogg_int64_t, int))           &_fseek64_wrap,
		(int (*)(void *))                             &fclose,
		(long (*)(void *))                            &ftell
	};
	
	if(ov_open_callbacks(pFile, &mVorbisFile, NULL, 0, callbacks) < 0) {
		throw std::runtime_error(String("Failed to read vorbis file - ") + sFile);
	};

	vorbis_info& info = *ov_info(&mVorbisFile, -1);
 
    if(info.channels == 1)
        mFormat = AUDIODATA_MONO_16;
    else
        mFormat = AUDIODATA_STEREO_16;

	mBitRate = info.rate;
};

VorbisData::~VorbisData() {
};

bool VorbisData::getData(const WtfEngine::NonCopyBuffer<>::tRef &rBuffer) {
	int numRead = 0, result;

	while(numRead < rBuffer->getCount()) {
		result = ov_read(&mVorbisFile, (char *)rBuffer->getData() + numRead, rBuffer->getCount() - numRead, 0,
			2, 1, &mPosition);
		
		if(result < 0) {
			throw std::runtime_error(String("Vorbis read error in ") + getName());
		} else if (result == 0) {
			break;
		} else {
			numRead += result;
		};
	};
	
	return (numRead > 0);
};

void VorbisData::Reset() {
	ov_time_seek(&mVorbisFile, 0.0);
	mPosition = 0;
};
